﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;

namespace CardPlay.Model.CardModel
{
    public class DealSequence : IDealAction
    {
        public static class Delimiter
        {
            public const char CompoundAction = ';';
            public const char Step = ',';
        }

        private readonly List<IDealAction> _script = new List<IDealAction>();

        public DealSequence()
        {
        }

        public DealSequence(IEnumerable<IDealAction> actions)
        {
            Contract.Requires<ArgumentNullException>(actions != null);
            _script.AddRange(actions);
        }

        public DealSequence(string target, string script)
        {
            Contract.Requires<ArgumentNullException>(target != null, "target");
            
            uint step = 0;
            
            foreach (var instruction in script.Split(Delimiter.CompoundAction))
                Add(ParseInstruction(step++, target, instruction));
        }

        public void Add(IDealAction action)
        {
            if (action != null)
                _script.Add(action);
        }

        public bool Execute(IDealContext context)
        {
            for (var i = 0; i < _script.Count;)
            {
                if (_script[i].Execute(context))
                    _script.RemoveAt(i);
                else
                    ++i;
            }
        
            return _script.Count == 0;
        }

        public static char[] Delimiters
        {
            get { return new[] { Delimiter.CompoundAction, Delimiter.Step }; }
        }

        private static IDealAction ParseInstruction(uint step, string target, string compoundInstruction)
        {
#if Smartphone
            // NOT SUPPORTED: StringSplitOptions.RemoveEmptyEntries
            var actions = from s in script.Split(actionDelimiters) where ! String.IsNullOrEmpty(s) select s;
#else
            var instructions = compoundInstruction.Split(new[] { Delimiter.Step }, StringSplitOptions.RemoveEmptyEntries);
#endif

            var actionSequence = new DealSequence();
            
            foreach (var action in instructions.Select(DealCardAction.Parse))
            {
                action.Step = step;
                action.Target = target;

                actionSequence.Add(action);
            }
                
            return actionSequence;
        }
    }
}
